home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / utility / slice.zip / SLICE.ASM < prev    next >
Assembly Source File  |  1989-05-16  |  34KB  |  885 lines

  1.         PAGE    55,132
  2.         TITLE   "SLICE - Break file for multiple diskettes"
  3.  
  4. CSEG        SEGMENT PARA PUBLIC 'CODE'
  5.         ASSUME  CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
  6.  
  7. ; ---------------------------------------------------------------------------
  8. ;   DTA structure for DOS "find matching" call
  9. ; ---------------------------------------------------------------------------
  10.         ORG     80H             ; dta offset
  11. DTA        DB        21 dup (0)            ; start of find file area
  12. DTA_ATTR    DB        0                ; file attribute
  13. DTA_TIME    DW        0                ; file time
  14. DTA_DATE    DW        0                ; file date
  15. DTA_LSIZ    DW        0                ; file lsw of size
  16. DTA_HSIZ    DW        0                ; file msw of size
  17. DTA_NAME    DB        12 DUP (0)            ; file name of file
  18. DTA_LEN     EQU     $-DTA            ; length of dta find entry
  19.  
  20.         ORG     100H            ; start of program area
  21. START:        JMP     MAIN            ; go to the code
  22.  
  23. ; ---------------------------------------------------------------------------
  24. ;   Common initialized work areas
  25. ; ---------------------------------------------------------------------------
  26. ARG        DW        0                ; addr of first argument
  27. FLOPDRV     DB        0,":\"                  ; output drive letter
  28. DESTFILE    DB        "            ",0        ; output file name
  29. DESTEXT     DW        0                ; pointer to extension
  30. DESTEXTC    DB        "0"                     ; 1st character of extension
  31. DESTNBR     DW        1                ; file extension counter
  32. RSTFLAG     DB        0                ; slice/restore flag
  33. CURRDIR     DB        ".",0                   ; argument for current directory
  34. IHANDLE     DW        0                ; input file handle
  35. OHANDLE     DW        0                ; output file handle
  36.  
  37. ; ---------------------------------------------------------------------------
  38. ;   Messages to user
  39. ; ---------------------------------------------------------------------------
  40. HEADER_MSG  DB        "SLICE   1.3 - (c) 1989 Ziff Communications Co.",0DH,0AH
  41.         DB        "PC Magazine ",254," Bob Flanders & Michael Holmes",0AH
  42.         DB        0DH,0AH
  43. DOLLAR        DB        "$"
  44. DONE        DB        "Done!",0AH,0DH,"$"
  45. FILENF        DB        "File not found$"
  46. NOCREATE    DB        "Error opening output$"
  47. NOROOM        DB        "Not enough room$"
  48. WRONGDISK   DB        "Wrong restore disk, insert"
  49. DISK        DB        " number "
  50. DISKNO        DB        "XX$"
  51. DRVNR        DB        "Must be removable media - (use /R to ignore)$"
  52. RDERROR     DB        "Error reading input$"
  53. WRTERROR    DB        "Error writing output$"
  54. FILEFND     DB        "File exists$"
  55. NEXTDISK    DB        "Next diskette$"
  56. READING     DB        "Reading$"
  57. WRITING     DB        "Writing$"
  58. HITANYKEY   DB        ", Press any key ..",07
  59. CRLF        DB        0DH,0AH,"$"
  60. FORMAT        DB        0DH,0AH,"format:",09H,"$"
  61. RSFORM        DB        "SPLICE   s:  d:[\path] [/R]",0DH,0AH,0AH
  62.         DB        "  where: s:    contains the SLICEd file",0DH,0AH
  63.         DB        "         d:    is the restore drive",0DH,0AH
  64.         DB        "         \path is the optional restore path",0Dh,0AH
  65.         DB        "         /R    ignore removeable status",0DH,0AH,"$"
  66. RESTORING   DB        "Restoring: "
  67. RESTFILE    DB        12 DUP (" "),0DH,0AH,"$"
  68. SLASH        DB        "\",0DH,"$"
  69.  
  70. ; ---------------------------------------------------------------------------
  71. ;   File ID Header
  72. ; ---------------------------------------------------------------------------
  73. RSTLAST     DB        0                ; last file flag
  74. RSTATTR     DB        0                ; file attributes
  75. RSTTIME     DW        0                ; file time
  76. RSTDATE     DW        0                ; file date
  77. RSTLSIZ     DW        0                ; file lsw of size
  78. RSTHSIZ     DW        0                ; file msw of size
  79. RSTNAME     DB        13 DUP (0)            ; file name of file
  80. RST_FFLEN   EQU     $-RSTATTR            ; length to move from ff area
  81. RSTSDTE     DD        0                ; date ..
  82. RSTSTME     DD        0                ; ..and time of save
  83. RST_LEN     EQU     $-RSTLAST            ; length of our file header
  84.  
  85. ; ---------------------------------------------------------------------------
  86. ;   MAIN - Mainline of program
  87. ; ---------------------------------------------------------------------------
  88. MAIN        PROC                ; start of program
  89.         CMP     RSTFLAG, 0            ; q. restoring?
  90.         JNZ     RESTORE            ; a. goto restore section
  91.  
  92.         CALL    INIT            ; initialize program
  93.         CALL    PARMS            ; check parameters
  94.         CALL    OPEN            ; open the input file
  95.         CALL    SAVE            ; copy/slice the file to output
  96.         JMP     SHORT MAIN10        ; return to dos
  97.  
  98. RESTORE:    CALL    INIT            ; perform restore setup
  99.         CALL    PARMS            ; check parameters
  100.         CALL    ROPEN            ; open the output file
  101.         CALL    RFILE            ; restore the file
  102.  
  103. MAIN10:     MOV     DX, OFFSET DONE        ; dx -> Done ..
  104.         CALL    DIE             ; .. say goodnight
  105. MAIN        ENDP
  106.  
  107. ; ---------------------------------------------------------------------------
  108. ;   INIT - Handle initialization
  109. ; ---------------------------------------------------------------------------
  110. INIT        PROC
  111.         CLD                 ; assure ascending
  112.         MOV     DX, OFFSET HEADER_MSG   ; dx -> header message
  113.         MOV     AH, 9            ; ah = print ascii$ message
  114.         INT     21H             ; .. ask DOS to do it
  115.         MOV     DESTNBR, 1            ; Initialize destination nbr
  116.         RET                 ; return to caller
  117. INIT        ENDP
  118.  
  119. ; ---------------------------------------------------------------------------
  120. ;   ROPEN - open the file to restore
  121. ; ---------------------------------------------------------------------------
  122. ROPEN        PROC
  123.         MOV     DI, OFFSET ROPENFILE    ; di -> work area
  124.         MOV     SI, ARG            ; si -> where to restore
  125.  
  126. ROPEN10:    MOVSB                ; move a character
  127.  
  128.         CMP     BYTE PTR [SI], 0        ; q. end of parm?
  129.         JNE     ROPEN10            ; a. yes .. continue
  130.  
  131.         CMP     BYTE PTR [DI-1], "\"    ; q. last byte a back-slash?
  132.         JE        ROPEN20            ; a. yes .. continue
  133.  
  134.         CMP     BYTE PTR [DI-1],":"     ; q. last byte a colon (drive)?
  135.         JE        ROPEN20            ; a. yes .. continue
  136.  
  137.         MOV     AL, "\"                 ; end as directory
  138.         STOSB
  139.  
  140. ROPEN20:    MOV     SI, OFFSET RSTNAME        ; si -> name of original file
  141.         MOV     BX, OFFSET RESTFILE     ; bx -> restore filename
  142.  
  143. ROPEN30:    LODSB                ; al = char of filename
  144.         STOSB                ; .. save it
  145.  
  146.         OR        AL, AL            ; q. end of file name?
  147.         JZ        ROPEN40            ; a. yes .. continue
  148.  
  149.         MOV     [BX], AL            ; save in message
  150.         INC     BX                ; bx -> next char
  151.         JMP     ROPEN30            ; .. continue
  152.  
  153. ROPEN40:    MOV     AH, 4EH            ; ah = find first
  154.         MOV     DX, OFFSET ROPENFILE    ; dx -> file to find
  155.         MOV     CX, 0FFH            ; .. any attribute
  156.         INT     21H             ; q. file found?
  157.         JC        ROPEN45            ; a. no .. continue
  158.  
  159.         MOV     DX, OFFSET FILEFND        ; dx -> file already exists
  160.         CALL    DIE             ; .. push up some daisies
  161.  
  162. ROPEN45:    MOV     AH, 3CH            ; ah = create function code
  163.         MOV     CL, RSTATTR         ; cx = original attributes
  164.         XOR     CH,CH            ; .. upper byte off
  165.         INT     21H             ; issue DOS call
  166.         JNC     ROPEN50            ; if no problems, continue
  167.  
  168.         MOV     DX, OFFSET NOCREATE     ; dx -> create error message
  169.         CALL    DIE             ; .. go deep six
  170.  
  171. ROPEN50:    MOV     OHANDLE, AX         ; save the file handle
  172.  
  173.         MOV     DX, OFFSET RESTORING    ; dx -> restore message
  174.         MOV     AH, 09H            ; ah = print ascii$
  175.         INT     21H             ; .. tell the user
  176.  
  177.         RET                 ; return to caller
  178. ROPEN        ENDP
  179.  
  180. ; ---------------------------------------------------------------------------
  181. ;   RFILE - restore file
  182. ; ---------------------------------------------------------------------------
  183. RFILE        PROC
  184.         CALL    NEXTFILE            ; create a file name
  185.  
  186. RFILE10:    MOV     DX, OFFSET FLOPDRV        ; dx -> file name
  187.         MOV     AX, 3D00H            ; al = open for read
  188.         INT     21H             ; .. ask DOS to do it.
  189.         JNC     RFILE20            ; ok .. continue
  190.  
  191. RFILE15:    MOV     DX, OFFSET WRONGDISK    ; dx -> wrong disk message
  192.         CALL    HITKEY            ; .. display and wait
  193.         JMP     RFILE10            ; .. and try again
  194.  
  195. RFILE20:    MOV     IHANDLE, AX         ; save file handle
  196.         MOV     BX, AX            ; bx = handle
  197.  
  198.         MOV     DX, OFFSET READING        ; dx -> "Reading"
  199.         CALL    OPMSG            ; .. show op what we're doing
  200.  
  201.         MOV     AH, 03FH            ; ah = read file
  202.         MOV     CX, RST_LEN         ; cx = len to read
  203.         MOV     DX, OFFSET BUFFER        ; dx -> buffer to read
  204.         INT     21H             ; read a buffer
  205.         JC        RFILE35            ; tell 'em we cant read it
  206.  
  207.         MOV     SI, DX            ; si -> buffer
  208.         MOV     DI, OFFSET RSTLAST        ; di -> our header
  209.         MOVSB                ; move last flag, setup for compare
  210.         MOV     CX, RST_LEN-1        ; cx = bytes to check
  211.        REPE CMPSB                ; q. headers the same?
  212.         JE        RFILE30            ; a. yes .. continue
  213.  
  214.         MOV     AH, 3EH            ; ah = close file
  215.         INT     21H             ; close output file
  216.         JMP     RFILE15            ; tell 'em
  217.  
  218. RFILE30:    MOV     AH, 03FH            ; ah = read file
  219.         MOV     BX, IHANDLE         ; bx = handle of file to read
  220.         MOV     CX, BUFLEN            ; cx = amount to read
  221.         MOV     DX, OFFSET BUFFER        ; dx -> buffer
  222.         INT     21H             ; read, please
  223.         JNC     RFILE40            ; if no error .. continue
  224.  
  225. RFILE35:    MOV     DX, OFFSET RDERROR        ; dx -> read error message
  226.         CALL    DIE             ; ..and die gracefully
  227.  
  228. RFILE40:    MOV     CX, AX            ; cx = bytes to write
  229.         JCXZ    RFILE80            ; if finished .. exit loop
  230.  
  231.         CALL    ACTION            ; tell the operator ..
  232.  
  233.         MOV     AH, 40H            ; ax = write
  234.         MOV     BX, OHANDLE         ; bx = output file handle
  235.         INT     21H             ; write a buffer
  236.         JC        RFILE50            ; error .. die
  237.  
  238.         CMP     AX, CX            ; q. able to write it?
  239.         JE        RFILE30            ; a. no .. tell 'em
  240.  
  241.         MOV     DI, OFFSET NOROOM        ; di -> wontfit msg
  242.         JMP     SHORT RFILE60        ; ..and exit gracefully
  243.  
  244. RFILE50:    MOV     DI, OFFSET WRTERROR     ; di -> write error message
  245.  
  246. RFILE60:    MOV     AH, 41H            ; ah = delete function
  247.         MOV     DX, OFFSET ROPENFILE    ; dx -> filename
  248.         INT     21H             ; issue DOS call
  249.  
  250.         MOV     DX, DI            ; dx -> error message to give
  251.         CALL    DIE             ; ..make my day, punk!
  252.  
  253. RFILE80:    MOV     AH, 3EH            ; ah = close file
  254.         INT     21H             ; close output file
  255.  
  256.         CMP     RSTLAST, 0            ; q. end of file
  257.         JNE     RFILE90            ; a. no .. continue
  258.  
  259.         MOV     DX, OFFSET NEXTDISK     ; dx -> next disk message
  260.         CALL    HITKEY            ; display message and wait
  261.         JMP     RFILE            ; .. get next file
  262.  
  263. RFILE90:    RET                 ; else .. return to caller
  264. RFILE        ENDP
  265.  
  266. ; ---------------------------------------------------------------------------
  267. ;   OPMSG - Tell about the operation; dx -> operation in progress, ASCII$
  268. ; ---------------------------------------------------------------------------
  269.  
  270. OPMSG        PROC
  271.         MOV     AH, 09H            ; ax = display a string
  272.         INT     21H             ; .. display it
  273.         MOV     DX, OFFSET DISK        ; dx -> string
  274.         MOV     AH, 09H            ; ax = display a string
  275.         INT     21H             ; .. display it
  276.         MOV     DX, OFFSET CRLF        ; dx -> string
  277.         MOV     AH, 09H            ; ax = display a string
  278.         INT     21H             ; .. display it
  279.         RET                 ; ..and return to caller
  280. OPMSG        ENDP
  281.  
  282. ; ---------------------------------------------------------------------------
  283. ;   ACTION - Entertain the operator
  284. ; ---------------------------------------------------------------------------
  285.  
  286. ACTION        PROC
  287.         PUSH    AX                ; save regs
  288.         PUSH    DX
  289.  
  290.         MOV     DX, OFFSET SLASH        ; dx -> action string
  291.         MOV     AH, 09H            ; ax = display a string
  292.         INT     21H             ; .. display it
  293.         CMP     SLASH, "\"              ; q. backslash?
  294.         JE        ACTION10            ; a. yes .. change to slash
  295.         MOV     SLASH, "\"              ; .. else .. set to backslash
  296.         JMP     SHORT ACTION90        ; .. and continue
  297.  
  298. ACTION10:   MOV     SLASH, "/"              ; change to slash
  299.  
  300. ACTION90:   POP     DX                ; restore regs
  301.         POP     AX
  302.         RET
  303. ACTION        ENDP
  304.  
  305. ; ---------------------------------------------------------------------------
  306. ;   NEXTFILE - Build next filename
  307. ; ---------------------------------------------------------------------------
  308.  
  309. NEXTFILE    PROC
  310.         MOV     AX, DESTNBR         ; ax = current count
  311.         MOV     BH, 10            ; bh = divisor
  312.         DIV     BH                ; al = tens, ah = units
  313.         OR        AX, 3030H            ; ax = ascii values
  314.         MOV     BX, DESTEXT         ; bx -> 2nd char of extension
  315.         MOV     [BX], AX            ; store rest of extension
  316.         MOV     WORD PTR DISKNO, AX     ; .. and in message
  317.         INC     DESTNBR            ; increment for next time
  318.         RET                 ; ..and return to caller
  319. NEXTFILE    ENDP
  320.  
  321. ; ---------------------------------------------------------------------------
  322. ;   HITKEY - Allow user to change diskettes; dx -> first message
  323. ; ---------------------------------------------------------------------------
  324. HITKEY        PROC
  325.         MOV     AH, 9H            ; ah = print string
  326.         INT     21H             ; .. call dos to print message
  327.  
  328.         MOV     DX, OFFSET HITANYKEY    ; dx -> prompt
  329.         INT     21H             ; issue prompt message
  330.  
  331.         MOV     AX, 0C08H            ; ax = clear buffer, wait for key
  332.         INT     21H             ; issue DOS call
  333.  
  334.         OR        AL, AL            ; q. function key hit?
  335.         JNZ     HITKEY90            ; a. no .. exit
  336.  
  337.         MOV     AH, 08H            ; ah = wait for key
  338.         INT     21H             ; issue DOS call
  339.  
  340. HITKEY90:   RET
  341. HITKEY        ENDP
  342.  
  343. ; ---------------------------------------------------------------------------
  344. ;   PARMS - Parses the command line
  345. ; ---------------------------------------------------------------------------
  346. PARMS        PROC
  347.         CALL    UPCASE            ; upper case the parm area
  348.  
  349.         CALL    CHKRMV            ; check for removable switch
  350.  
  351.         MOV     SI, 81H            ; si -> parms area
  352. PARMS10:    LODSB                ; get parameter character
  353.  
  354.         CMP     AL, 0DH            ; q. end of line?
  355.         JE        PARMS50            ; a. yes .. exit
  356.         CMP     AL, " "                 ; q. blank?
  357.         JNA     PARMS10            ; a. yes .. skip
  358.         CALL    ARGCHK            ; set the argument
  359.         JC        PARMSERR            ; .. die on an error
  360.  
  361. PARMS30:    LODSB                ; get next character
  362.         CMP     AL, 0DH            ; q. end of line?
  363.         JE        PARMS50            ; a. yes .. process
  364.         CMP     AL, " "                 ; q. end of PARMS?
  365.         JA        PARMS30            ; a. no .. next char
  366.  
  367.         MOV     BYTE PTR [SI-1], 0        ; end the parameter
  368.         JMP     PARMS10            ; .. look for next
  369.  
  370. PARMS50:    MOV     BYTE PTR [SI-1], 0        ; end the parameter
  371.  
  372.         CMP     ARG, 0            ; q. PARMS 1 available?
  373.         JNE     PARMS60            ; a. no .. error
  374.  
  375.         CMP     RSTFLAG, 0            ; q. restoring?
  376.         JE        PARMSERR            ; a. no .. error
  377.  
  378.         MOV     ARG, OFFSET CURRDIR     ; arg -> current directory
  379.  
  380. PARMS60:    CMP     FLOPDRV, 0            ; q. Drive given?
  381.         JE        PARMSERR            ; a. no .. error also
  382.  
  383.         RET                 ; .. else .. return to caller
  384.  
  385. PARMSERR:   MOV     DX, OFFSET FORMAT        ; dx -> format message
  386.         MOV     AH, 09H            ; ah = print ascii$
  387.         INT     21H             ; hey DOS .. print it!
  388.  
  389.         MOV     DX, OFFSET RSFORM        ; dx -> restore format
  390.  
  391.         CMP     RSTFLAG, 0            ; q. restore?
  392.         JNZ     PARMSERR1            ; a. yes .. die now
  393.  
  394.         MOV     DX, OFFSET SPFORM        ; dx -> slice format
  395.  
  396. PARMSERR1:  CALL    DIE             ; .. play taps
  397. PARMS        ENDP
  398.  
  399. ; ---------------------------------------------------------------------------
  400. ;   ARGCHK - Setup pointers to command line args; si -> 2nd char in arg
  401. ;         Exit: ARG or FLOPDRV filled in; Carry set if > 2 args
  402. ; ---------------------------------------------------------------------------
  403. ARGCHK        PROC
  404.         LEA     BX, [SI-1]            ; bx -> argument
  405.  
  406.         CMP     RSTFLAG, 0            ; q. restoring?
  407.         JE        ARG05            ; a. no .. continue
  408.  
  409.         CMP     FLOPDRV, 0            ; q. drive filled in?
  410.         JE        ARG20            ; a. no .. fill it in
  411.  
  412. ARG05:        CMP     ARG, 0            ; q. ARG filled in?
  413.         JNE     ARG10            ; a. yes .. check 2
  414.         MOV     ARG, BX            ; save ARG pointer
  415.         JMP     SHORT ARG90         ; .. exit ok!
  416.  
  417. ARG10:        CMP     FLOPDRV, 0            ; q. drive filled in?
  418.         JE        ARG20            ; a. no .. fill it in
  419.         STC                 ; else .. error
  420.         RET                 ; .. and return to caller
  421.  
  422. ARG20:        MOV     FLOPDRV, AL         ; save drive
  423.         MOV     SPLICEDRV, AL        ; .. in file and program names
  424.  
  425.         OR        RMVSTAT, 0            ; q. ignore removable?
  426.         JNZ     ARG90            ; a. yes .. do not check drive
  427.  
  428.         MOV     BL, AL            ; bl = drive letter
  429.         SUB     BL, "@"                 ; bl = drive number
  430.         MOV     AX, 4408H            ; ax = ioctl, removable?
  431.         INT     21H             ; issue DOS call
  432.  
  433.         OR        AL, AL            ; q. removable media drive?
  434.         JZ        ARG90            ; a. yes .. return
  435.  
  436.         MOV     DX, OFFSET DRVNR        ; dx -> error message
  437.         CALL    DIE             ; issue non-removable message
  438.  
  439. ARG90:        CLC                 ; show no error
  440.         RET                 ; return to caller
  441. ARGCHK        ENDP
  442.  
  443. ; ---------------------------------------------------------------------------
  444. ;   UPCASE - Convert command line arguments to uppercase
  445. ; ---------------------------------------------------------------------------
  446. UPCASE        PROC
  447.         PUSH    SI                ; save caller regs
  448.         PUSH    DI
  449.         MOV     SI, 81H            ; si -> start of parm area
  450.         MOV     DI, SI            ; .. same for di
  451.         CLD                 ; .. assure ascending
  452.  
  453. UPCASE10:   LODSB                ; al = char
  454.         CMP     AL, 0DH            ; q. end of line?
  455.         JE        UPCASE90            ; a. yes .. end of line!
  456.         CMP     AL, "a"                 ; q. is it below 'a'?
  457.         JB        UPCASE20            ; a. yes .. continue
  458.         CMP     AL, "z"                 ; q. is it above 'z'?
  459.         JA        UPCASE20            ; a. yes .. continue
  460.         SUB     AL, 20H            ; set to upper case
  461.  
  462. UPCASE20:   STOSB                ; save the byte
  463.         JMP     UPCASE10            ; .. and continue
  464.  
  465. UPCASE90:   POP     DI                ; restore caller regs
  466.         POP     SI
  467.         RET                 ; .. and return to caller
  468. UPCASE        ENDP
  469.  
  470. ; ---------------------------------------------------------------------------
  471. ;   CHKRMV - check command line for /R argument
  472. ; ---------------------------------------------------------------------------
  473. CHKRMV        PROC
  474.         PUSH    DI                ; save di
  475.  
  476.         MOV     RMVSTAT, 0            ; set to check removable status
  477.  
  478.         CLD                 ; increment di
  479.         MOV     AL, '/'                 ; al = char to scan for
  480.         MOV     DI, 81H            ; di -> string to scan
  481.         MOV     CL, BYTE PTR DS:[80H]   ; cl = command line length
  482.  
  483.       REPNZ SCASB                ; q. slash found?
  484.         JNE     CHKRMV90            ; a. no .. exit
  485.  
  486.         CMP     BYTE PTR [DI], 'R'      ; q. /R?
  487.         JNE     CHKRMV90            ; a. no .. exit
  488.  
  489.         MOV     RMVSTAT, 1            ; set to not check removable
  490.         MOV     WORD PTR [DI-1], '  '   ; blank out /R
  491.  
  492. CHKRMV90:   POP     DI                ; restore caller regs
  493.         RET                 ; .. and return to caller
  494. CHKRMV        ENDP
  495.  
  496. ; ---------------------------------------------------------------------------
  497. ;   DIE - Display an error message and return to DOS; dx -> ascii$ error msg
  498. ; ---------------------------------------------------------------------------
  499. DIE        PROC
  500.         MOV     AH, 9H            ; ah = print string
  501.         INT     21H             ; .. call dos to print error
  502.  
  503.         MOV     BX, IHANDLE         ; bx = input file handle
  504.         OR        BX, BX            ; q. file opened?
  505.         JZ        DIE90            ; a. no .. try output file
  506.  
  507.         MOV     AH, 3EH            ; ah = close file
  508.         INT     21H             ; .. ask DOS to do it
  509.  
  510. DIE90:        MOV     BX, OHANDLE         ; bx = output file handle
  511.         OR        BX, BX            ; q. file opened?
  512.         JZ        DIE95            ; a. no .. just exit
  513.  
  514.         MOV     AH, 3EH            ; ah = close file
  515.         INT     21H             ; .. ask DOS to do it
  516.  
  517. DIE95:        MOV     AX, 4C00H            ; ax = exit
  518.         INT     21H             ; .. terminate routine
  519. DIE        ENDP
  520.  
  521.  
  522. RESTLIMIT   EQU     $                ; only need up to here
  523.  
  524.  
  525. ; ---------------------------------------------------------------------------
  526. ;   Slice only areas and messages
  527. ; ---------------------------------------------------------------------------
  528. SPFORM        DB        "SLICE     [s:\path\]filename[.ext] "
  529.         DB        " d:",0DH,0AH,0AH
  530.         DB        " where:  s:\path\filename.ext is the file to SLICE."
  531.         DB        0DH,0AH
  532.         DB        "         d:  is a removable media drive.",0DH,0AH,"$"
  533. ZEROLEN     DB        "Input file empty",0DH,0AH,"$"
  534. NOCOM        DB        "Program won't fit",0DH,0AH,"$"
  535. SPLICEDRV   DB        "x:\"
  536. SPLICE        DB        "SPLICE.COM",0
  537.  
  538. ; ---------------------------------------------------------------------------
  539. ;   OPEN - Opens next file to process; Carry indicates file would not open.
  540. ; ---------------------------------------------------------------------------
  541. OPEN        PROC
  542.         MOV     DX, ARG            ; dx -> file name
  543.         MOV     AX, 3D00H            ; al = open for read
  544.         INT     21H             ; .. ask DOS to do it.
  545.         JC        OPEN05            ; ok .. continue
  546.  
  547.         MOV     IHANDLE, AX         ; save file handle
  548.  
  549.         MOV     AH, 4EH            ; ah = find first
  550.         MOV     DX, ARG            ; dx -> file to find
  551.         XOR     CX, CX            ; cx = search attribute
  552.         INT     21H             ; q. find first file ok?
  553.         JNC     OPEN10            ; a. yes .. continue
  554.  
  555. OPEN05:     MOV     DX, OFFSET FILENF        ; dx -> file not found
  556.         CALL    DIE             ; .. gasp your final breath
  557.  
  558. OPEN10:     MOV     AX, DS:DTA_LSIZ        ; ax = lsw of size
  559.         OR        AX, DS:DTA_HSIZ        ; q. any data?
  560.         JNZ     OPEN90            ; a. yes ..continue
  561.  
  562.         MOV     DX, OFFSET ZEROLEN        ; dx -> file contains no data
  563.         CALL    DIE             ; .. dearly beloved ...
  564.  
  565. OPEN90:     RET
  566. OPEN        ENDP
  567.  
  568. ; ---------------------------------------------------------------------------
  569. ;   SAVE - Handle building slice files on destination
  570. ; ---------------------------------------------------------------------------
  571. SAVE        PROC
  572.         CALL    BLD_RESTORE         ; build restore program
  573.  
  574. SAVE10:     MOV     AH, 03FH            ; ah = read file
  575.         MOV     BX, IHANDLE         ; bx = handle of file to read
  576.         MOV     CX, BUFLEN            ; cx = amount to read
  577.         MOV     DX, OFFSET BUFFER        ; dx -> buffer
  578.         INT     21H             ; read, please
  579.         JNC     SAVE20            ; if no error .. continue
  580.  
  581.         MOV     DX, OFFSET RDERROR        ; dx -> read error message
  582.         CALL    DIE             ; ..and die gracefully
  583.  
  584. SAVE20:     CALL    WRITE            ; ..and write out a buffer full
  585.         JC        SAVE90            ; if finished .. exit loop
  586.         JMP     SAVE10            ; else .. get next buffer
  587.  
  588. SAVE90:     RET                 ; return to caller
  589. SAVE        ENDP
  590.  
  591. ; ---------------------------------------------------------------------------
  592. ;   BLD_RESTORE - Build the restore program
  593. ; ---------------------------------------------------------------------------
  594. BLD_RESTORE PROC
  595.         MOV     AH, 2AH            ; ah = get date function call
  596.         INT     21H             ; issue DOS call
  597.  
  598.         MOV     WORD PTR RSTSDTE, CX    ; save year
  599.         MOV     WORD PTR RSTSDTE+2, DX  ; ..and month and day
  600.  
  601.         MOV     AH, 2CH            ; ah = get time function call
  602.         INT     21H             ; issue DOS call
  603.  
  604.         MOV     WORD PTR RSTSTME, CX    ; save hours and minutes
  605.         MOV     WORD PTR RSTSTME+2, DX  ; ..and seconds and hundredths
  606.  
  607.         MOV     SI, OFFSET DTA_ATTR     ; si -> source string
  608.         MOV     DI, OFFSET RSTATTR        ; di -> save area
  609.         MOV     CX, RST_FFLEN        ; cx = length to move
  610.     REP MOVSB                ; copy string
  611.  
  612.         MOV     DI, OFFSET HEADER_MSG   ; di -> program name
  613.         MOV     SI, OFFSET SPLICE        ; si -> restore program name
  614.         MOV     CX, 7            ; cx = length
  615.     REP MOVSB                ; .. setup program name
  616.  
  617.         MOV     SI, OFFSET DTA_NAME     ; si -> source file name
  618.         MOV     DI, OFFSET DESTFILE     ; di -> work file name
  619.         MOV     CX, 9            ; cx = length to move
  620.  
  621. BLD_REST10: LODSB                ; al = char from filename
  622.  
  623.         CMP     AL, "."                 ; q. end of filename?
  624.         JE        BLD_REST30            ; a. yes .. exit loop
  625.         OR        AL, AL            ; q. end of string?
  626.         JZ        BLD_REST20            ; a. yes .. exit loop
  627.  
  628.         STOSB                ; save character
  629.         LOOP    BLD_REST10            ; ..and loop till end of string
  630.  
  631. BLD_REST20: MOV     AL, "."                 ; assure file separator char
  632. BLD_REST30: STOSB                ; save the separator
  633.  
  634.         MOV     DESTEXT, DI         ; save pointer to file extension
  635.  
  636.         CMP     BYTE PTR [SI-1], "."    ; q. was extension found?
  637.         JNE     BLD_REST32            ; a. no .. allow default
  638.  
  639.         LODSB                ; get 1st char after extenstion
  640.         MOV     DESTEXTC, AL        ; ..and save for later
  641.  
  642. BLD_REST32: MOV     RSTFLAG, 1            ; set restore flag
  643.  
  644.         MOV     AL, DESTEXTC        ; al = 1st char of extension
  645.         MOV     DI, DESTEXT         ; di -> position in filename
  646.         STOSB                ; save 1st character
  647.         MOV     DESTEXT, DI         ; save pointer to 2nd char
  648.  
  649. BLD_REST35: MOV     DX, OFFSET SPLICEDRV    ; dx -> SPLICE program name
  650.         CALL    CREATE            ; create the new file
  651.  
  652.         PUSH    WORD PTR FLOPDRV        ; save drive parameter
  653.         PUSH    ARG             ; .. and ARG
  654.         MOV     FLOPDRV, 0            ; zero ..
  655.         MOV     ARG, 0            ; .. them out
  656.  
  657.         MOV     AH, 40H            ; ah = write function code
  658.         MOV     CX, OFFSET RESTLIMIT    ; cx = length to move
  659.         MOV     DX, OFFSET START        ; dx -> start of program
  660.         SUB     CX, DX            ; .. forget the PSP
  661.         INT     21H             ; issue DOS call
  662.  
  663.         POP     ARG             ; restore ..
  664.         POP     WORD PTR FLOPDRV        ; .. parameters
  665.         JC        BLD_REST40            ; if ok, continue
  666.  
  667.         CMP     AX, CX            ; q. all of pgm get out?
  668.         JE        BLD_REST50            ; a. yes .. continue
  669.  
  670. BLD_REST40: MOV     AH, 3EH            ; ah = close function
  671.         INT     21H             ; close file
  672.  
  673.         CALL    DELETE            ; delete output file
  674.         MOV     DX, OFFSET NOCOM        ; dx -> no room at the inn
  675.         CALL    HITKEY            ; ..issue message
  676.         JMP     BLD_REST35            ; ..and try with a new diskette
  677.  
  678. BLD_REST50: MOV     AH, 3EH            ; ah = close file
  679.         INT     21H             ; .. ask DOS to do it
  680.  
  681.         RET                 ; return to caller
  682. BLD_RESTORE ENDP
  683.  
  684. ; ---------------------------------------------------------------------------
  685. ;   WRITE - Write a file segment; ax = nbr of bytes to write (0 if EOF)
  686. ;                Exit: Carry set if EOF processing complete
  687. ; ---------------------------------------------------------------------------
  688. WRITE        PROC
  689.         MOV     BX, OHANDLE         ; bx = handle number
  690.         MOV     CX, AX            ; q. anything to write?
  691.         JCXZ    WRITE50            ; a. no .. EOF request
  692.  
  693.         MOV     DX, OFFSET BUFFER        ; dx -> start of buffer
  694.         OR        BX, BX            ; q. handle open?
  695.         JNZ     WRITE40            ; a. yes .. continue
  696.  
  697. WRITE05:    PUSH    CX                ; save length
  698.         PUSH    DX                ; ..and buffer address
  699.         CALL    NEXTFILE            ; build extension for next file
  700.  
  701. WRITE10:    MOV     DX, OFFSET FLOPDRV        ; dx -> file to create
  702.         CALL    CREATE            ; open new file
  703.  
  704.         MOV     DX, OFFSET WRITING        ; dx -> "Writing"
  705.         CALL    OPMSG            ; .. show op what we're doing
  706.  
  707.         MOV     OHANDLE, BX         ; save file handle
  708.         MOV     CX, RST_LEN         ; cx = length of header
  709.         CALL    HOWMUCH            ; update remaining disk space
  710.         MOV     AH, 40H            ; ah = write file function
  711.         MOV     DX, OFFSET RSTLAST        ; dx -> our file header
  712.         INT     21H             ; issue DOS call
  713.         JNC     WRITE20            ; if no error .. continue
  714.  
  715.         MOV     DX, OFFSET WRTERROR     ; dx -> error message
  716.         CALL    DIE             ; ..then display and die
  717.  
  718. WRITE20:    CMP     AX, CX            ; q. write out all of header?
  719.         JE        WRITE30            ; a. yes .. continue
  720.  
  721.         MOV     AH, 3EH            ; ah = close function
  722.         INT     21H             ; issue DOS call
  723.  
  724.         CALL    DELETE            ; delete new file
  725.  
  726.         MOV     DX, OFFSET NOROOM        ; dx -> next disk message
  727.         CALL    HITKEY            ; issue message and wait
  728.         JMP     WRITE10            ; ..try to get next file
  729.  
  730. WRITE30:    POP     DX                ; restore registers
  731.         POP     CX                ;
  732.  
  733. WRITE40:    CALL    HOWMUCH            ; get how much to write
  734.  
  735.         CALL    ACTION            ; tell the operator ..
  736.  
  737.         MOV     AH, 40H            ; ah = write file
  738.         INT     21H             ; issue DOS call
  739.         JNC     WRITE45            ; die on any error
  740.  
  741.         MOV     DX, OFFSET WRTERROR     ; dx -> general error msg
  742.         CALL    DIE             ; issue msg and terminate
  743.  
  744. WRITE45:    ADD     DX, AX            ; dx -> next buffer address
  745.         MOV     CX, DI            ; cx = remainder of bytes to write
  746.         JCXZ    WRITE48            ; if no more, exit
  747.  
  748.         PUSH    DX                ; save buffer address
  749.         MOV     AH, 3EH            ; ah = close function
  750.         INT     21H             ; issue DOS call
  751.  
  752.         MOV     DX, OFFSET NEXTDISK     ; dx -> next disk message
  753.         CALL    HITKEY            ; display message and wait
  754.         POP     DX                ; .. restore buffer address
  755.         JMP     WRITE05            ; ..then get next file
  756.  
  757. WRITE48:    CLC                 ; clear carry for caller
  758.         RET                 ; ..and return
  759.  
  760.  
  761. WRITE50:    OR        BX, BX            ; q. handle open?
  762.         JZ        WRITE60            ; a. no .. continue
  763.  
  764.         MOV     AX, 4200H            ; ah = position file
  765.         XOR     CX, CX            ; cx = file position
  766.         XOR     DX, DX            ; dx = msb of file position
  767.         INT     21H             ; position to top of file
  768.  
  769.         MOV     RSTLAST, 1            ; set flag
  770.         MOV     AH, 40H            ; ah = write function
  771.         MOV     CX, 1            ; cx = length
  772.         MOV     DX, OFFSET RSTLAST        ; dx -> buffer
  773.         INT     21H             ; write eof marker in header
  774.  
  775.         MOV     AH, 3EH            ; ah = close function
  776.         INT     21H             ; issue DOS call
  777.  
  778. WRITE60:    STC                 ; set carry flag
  779.         RET                 ; ..and return to caller
  780. WRITE        ENDP
  781.  
  782. ; ---------------------------------------------------------------------------
  783. ;   HOWMUCH - Calculate how much to write; cx = requested amount to write
  784. ;                     Exit: cx = nbr of bytes which will fit
  785. ;                       di = remainder
  786. ; ---------------------------------------------------------------------------
  787. HOWMUCH     PROC
  788.         PUSH    DX                ; save registers
  789.  
  790.         MOV     AX, WORD PTR AVAIL        ; get howmuch is available
  791.         MOV     DX, WORD PTR AVAIL+2    ; . . . .
  792.         MOV     DI, 0            ; assume everything will fit
  793.  
  794.         OR        DX, DX            ; q. more than 64k?
  795.         JNZ     HOWMUCH80            ; a. no .. must be less than 64k
  796.  
  797.         CMP     CX, AX            ; q. enough room left?
  798.         JNA     HOWMUCH80            ; a. yes .. use it all
  799.  
  800.         MOV     DI, CX            ; di = nbr requested
  801.         SUB     DI, AX            ; di = remainder
  802.         MOV     CX, AX            ; cx = nbr to write
  803.  
  804. HOWMUCH80:  SUB     AX, CX            ; ax = new available
  805.         SBB     DX, 0            ; dx:ax = new available
  806.         MOV     WORD PTR AVAIL, AX        ; store for later
  807.         MOV     WORD PTR AVAIL+2, DX    ; . . . .
  808.  
  809. HOWMUCH90:  POP     DX                ; restore registers
  810.         RET                 ; ..and return
  811. HOWMUCH     ENDP
  812.  
  813. ; ---------------------------------------------------------------------------
  814. ;   CREATE - Create new file; dx -> file to open
  815. ;            Exit: bx = handle of opened file
  816. ; ---------------------------------------------------------------------------
  817. CREATE        PROC
  818.         MOV     BP, DX            ; save file name pointer
  819.  
  820. CREATE10:   MOV     AH, 36H            ; ah = get drive info
  821.         MOV     DL, FLOPDRV         ; dl = drive letter
  822.         SUB     DL, "@"                 ; dl = drive number
  823.         INT     21H             ; get free space
  824.  
  825.         CMP     AX, -1            ; q. drive ok?
  826.         JE        CREATE15            ; a. no .. next disk
  827.  
  828.         OR        BX, BX            ; q. any clusters available?
  829.         JNZ     CREATE18            ; a. yes .. build new file
  830.  
  831. CREATE15:   MOV     DX, OFFSET NOROOM        ; dx -> no room at inn message
  832.         CALL    HITKEY            ; get new diskette
  833.         JMP     CREATE10            ; ..try again
  834.  
  835. CREATE18:   MUL     BX                ; dx:ax = nbr of sectors available
  836.         MUL     CX                ; dx:ax = nbr of bytes available
  837.         MOV     WORD PTR AVAIL, AX        ; store howmuch is available
  838.         MOV     WORD PTR AVAIL+2, DX    ; . . . .
  839.  
  840.         MOV     AH, 4EH            ; ah = find first function code
  841.         MOV     CX, 0FFH            ; cx = any attributes
  842.         MOV     DX, BP            ; dx -> filename
  843.         INT     21H             ; issue DOS call
  844.         JC        CREATE20            ; if not available, create it
  845.  
  846.         MOV     DX, OFFSET FILEFND        ; dx -> file found message
  847.         CALL    HITKEY            ; let user change diskette
  848.         JMP     CREATE10            ; ..then try again
  849.  
  850. CREATE20:   MOV     AH, 3CH            ; ah = create function code
  851.         XOR     CX, CX            ; cx = no (special) attributes
  852.         INT     21H             ; issue DOS call
  853.         JNC     CREATE90            ; if problems, exit
  854.  
  855.         MOV     DX, OFFSET NOCREATE     ; dx -> create error message
  856.         CALL    DIE             ; ..and die
  857.  
  858. CREATE90:   MOV     BX, AX            ; bx = handle
  859.         RET                 ; ..and return to caller
  860. CREATE        ENDP
  861.  
  862. ; ---------------------------------------------------------------------------
  863. ;   DELETE - Delete a file
  864. ; ---------------------------------------------------------------------------
  865. DELETE        PROC
  866.         MOV     AH, 41H            ; ah = delete function
  867.         MOV     DX, OFFSET FLOPDRV        ; dx -> filename
  868.         INT     21H             ; issue DOS call
  869.  
  870.         RET                 ; ..and return
  871. DELETE        ENDP
  872.  
  873. ; ---------------------------------------------------------------------------
  874. ;   Uninitialized data areas
  875. ; ---------------------------------------------------------------------------
  876. UDATA        EQU     $                ; start of unitialized data
  877. ROPENFILE   EQU     BYTE PTR UDATA        ; word area for ropen
  878. AVAIL        EQU     DWORD PTR ROPENFILE+65  ; available output space
  879. RMVSTAT     EQU     BYTE PTR AVAIL+4        ; ignore removable if non-zero
  880. BUFFER        EQU     BYTE PTR RMVSTAT+1        ; file buffer
  881. BUFLEN        EQU     32*1024            ; length of buffer
  882.  
  883. CSEG        ENDS                ; end of code segment
  884.         END     START
  885.